﻿using System;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;

namespace MvcOSGi.Shell.Infra
{
    public static class LambdaExtensions
    {
        public static Action<T, object> GetPropertySetMethod<T>(this PropertyInfo propertyInfo)
        {
            var method = propertyInfo.GetSetMethod();
            if (method == null) return null;
            var parameter = method.GetParameters().Single();
            var instance = Expression.Parameter(typeof(T), "instance");
            var argument = Expression.Parameter(typeof(object), "argument");
            var methodCall = Expression.Call(instance, method, Expression.Convert(argument, parameter.ParameterType));
            return Expression.Lambda<Action<T, object>>(methodCall, instance, argument).Compile();
        }

        public static Func<T, object> GetPropertyGetMethod<T>(this PropertyInfo propertyInfo)
        {
            var method = propertyInfo.GetGetMethod();
            if (method == null) return null;
            var instance = Expression.Parameter(typeof(T), "instance");
            var methodCall = Expression.Call(instance, method);
            return Expression.Lambda<Func<T, object>>(Expression.Convert(methodCall, typeof(object)), instance).Compile();
        }

        public static Func<T> GetConstructor<T>() where T : class, new()
        {
            var constructorInfo = typeof(T).GetConstructor(new Type[0]);
            return Expression.Lambda<Func<T>>(Expression.New(constructorInfo)).Compile();
        }
    }
}
